﻿using System;
using System.Collections.Specialized;
using System.Windows;
using LukasKopenec.LocalizationSupport;
using Notoric.Gui.Windows;

namespace Notoric.Gui.Commands
{
    /// <summary>
    /// Implements a command that closes the currently open project.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The command can execute is and only if the Projects collection of the Project Explorer 
    /// window contains 1 <see cref="Notoric.ViewModel.Elements.Project"/> instance.
    /// </para>
    /// <para>
    /// The execution proceeds as follows:
    /// <list type="number">
    /// <item>
    /// If the project has unsaved changes a message box is shown asking the user if he wants to save the project.
    /// </item>
    /// <item>
    /// If the answer is "Cancel" the execution of the command is canceled.
    /// </item>
    /// <item>
    /// If the answer is "Yes" the <see cref="SaveCommand"/> is executed.
    /// </item>
    /// <item>
    /// The <see cref="Notoric.ViewModel.Elements.Project.Close"/> method is called.
    /// </item>
    /// <item>
    /// The project's temporary file is deleted from the application's settings.
    /// </item>
    /// </list>
    /// </para>
    /// </remarks>
    public class CloseCommand : RibbonCommand
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="CloseCommand"/> instance.
        /// </summary>
        /// <param name="mainWindow">
        /// <para>
        /// Type: <see cref="MainWindow"/>
        /// </para>
        /// <para>
        /// Reference to the application's main window.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="mainWindow"/> is <see langword="null"/>.
        /// </exception>
        public CloseCommand(MainWindow mainWindow)
            : base(mainWindow)
        {
            mainWindow.ProjectExplorer.Projects.CollectionChanged += new NotifyCollectionChangedEventHandler(Projects_CollectionChanged);

            ScreenTipTitle = (string)LocalizationManager.GetValue("Ribbon.CommandTitles.AppMenu.Close");
            ScreenTipText = "Closes the current project.";
        }

        #endregion

        #region ICommand Members

        /// <inheritdoc/>
        public override bool CanExecute(object parameter)
        {
            return ApplicationWindow.ProjectExplorer.Projects.Count == 1;
        }

        /// <inheritdoc/>
        public override void Execute(object parameter)
        {
            var project = ApplicationWindow.ProjectExplorer.Projects[0];

            if (project.IsModified)
            {
                MessageBoxResult result = MessageBox.Show(
                    String.Format(
                        (string)LocalizationManager.GetValue("Application.ClosingModifiedProjectMessage"),
                        project.Name
                        ),
                    (string)LocalizationManager.GetValue("Application.Title"),
                    MessageBoxButton.YesNoCancel,
                    MessageBoxImage.Question
                    );

                switch (result)
                {
                    case MessageBoxResult.Cancel:
                        return;
                    case MessageBoxResult.Yes:
                        ApplicationWindow.SaveCmd.Execute(null);
                        break;
                }
            }

            for (int i = ApplicationWindow.DocumentPane.Items.Count - 1; i >= 0; --i)
                ((AvalonDock.DocumentContent)ApplicationWindow.DocumentPane.Items[i]).Close();
            
            project.Close();
            ApplicationWindow.ProjectExplorer.Projects.Clear();

            Properties.Settings.Default["TemporaryProjectFile"] = "";
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the projects collection of the project explorer window has changed.
        /// </summary>
        /// <remarks>
        /// <b>Operation:</b><br/>
        /// The handler raises the <see cref="RibbonCommand.CanExecuteChanged"/> event.
        /// </remarks>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void Projects_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            RaiseCanExecuteChanged();
        }

        #endregion
    }
}
